iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 5
0
Modern Web

試著把切版專案升級到 gulp4.0 吧系列 第 5

[試著把切版專案升級到 gulp4.0 吧] Day05 來自 gulp 的 hello world:gulp4 寫法

  • 分享至 

  • xImage
  •  

在 Gulp4 中,task() API 已經不被推薦,改成用 function 定義 task。使用 function 定義 task 有個好處,就是如果該 function 沒有被 export 出來的話,gulp cli 就沒辦法取用,讓 tasks 清單更加地簡潔。

而讓 function export 出來,跟把 module export 出來的用法是很像的。export 出 function 定義的 task 有兩種寫法:CommonJS 與 ESM 寫法。不過就先只單純看 gulp 4 的 task 寫法吧。

將 gulp 3.9.1 寫法轉成 gulp 4 寫法

當要在 gulp 建立 task 時,gulp 3.9.1 本來是使用 gulp.task() 的方式來建立 task,之後就能在 CLI 中透過 gulp 工作名稱 來執行 task。但在 gulp 4 中,官方不推薦使用 gulp.task() 的方式建立 task了;取而帶之的,是透過 function 工作名稱() {} 來建立 task,之後再用 exports.工作名稱 = 函式名稱 來導出 task,讓開發者能在 CLI 中執行 task。

附帶一提,require()exports 是 Node.js 要引用、導出 JavaScript module 的方式,屬於 CommonJS 規範。延伸討論會在 Day6 提到。

一、建立 gulp 4 的 task 函式

// gulpfile.js
// 在 CLI 輸入 gulp hello4CommonJS,會印出 hello gulp , CommonJS format

var gulp = require('gulp') 

function hello4CommonJS(cb) {
  console.log('hello gulp 4.0, CommonJS format' )
  cb();
}

exports.hello4CommonJS = hello4CommonJS

二、在 CLI 操作 gulp4

gulp hello4CommonJS
> hello gulp 4.0, CommonJS format

gulp 4 設定 task 從 CommonJS 改成 ESM 寫法

想引入 npm 的模組(套件)、或是 export 出 gulp 的函式,除了 Node.js 原生支援的 CommonJS 寫法外,也能使用 ES6 module 新引入的 import、export 語法。不過如果直接用的話,會出現問題:node.js 不認識 import 這個 keyword。

試著將 requireexprots 等 CommonJS 寫法改成 importexport 等ES6 module 寫法:

// gulpfile.js
// 在 CLI 輸入 gulp hello4ES6,會印出 錯誤訊息
import gulp from 'gulp' 

export function hello4ES6(cb) {
  console.log('hello gulp 4.0, ES6 format')
  cb()
}

結果會出現錯誤訊息,node.js 看不懂 import 這個關鍵字。

gulp hello4CommonJS

import gulp from 'gulp' // ES6 引入模組寫法
       ^^^^
SyntaxError: Unexpected identifier

因此,為了讓 node.js 認識 import 關鍵字,根據 gulp 在 npm 的建議,有兩個可嘗試的方式:一是開啟 node.js 的 esm module 功能,一是透過 babel 將 import 關鍵字轉成 require 這個 node.js 看得懂得關鍵字。這邊嘗試使用第二種方式。

一、首先,將 gulpfile.js 檔案改名為 gulpfile.babel.js,讓 gulp-cli 知道這個 gulpfile 檔案內有 ES6 語法,需要用 babel 去轉換。不過,若只改了檔名而沒有配套措施的話,在 CLI 輸入 gulp hello4ES6 後會出現錯誤訊息:

// gulpfile.babel.js
// 在 CLI 輸入 gulp hello4ES6,會印出錯誤訊息

import gulp from 'gulp' 

export function hello4ES6(cb) {
  console.log('hello gulp 4.0, ES6 format')
  cb()
}
gulp hello4CommonJS

[18:51:07] Failed to load external module @babel/register
[18:51:07] Failed to load external module babel-register
[18:51:08] Failed to load external module babel-core/register
[18:51:08] Failed to load external module babel/register

二、根據錯誤訊息與 gulp 在 npm 的說明,還需要在 CLI 安裝 babel 相關插件、新增 babel 設定,才能讓 gulpfile.babel.js 使用 ES6 的 import 語法

# 讓 gulp 內能使用 import/export 語法
npm install --save-dev @babel/register @babel/core @babel/preset-env

+ @babel/register@7.6.0
+ @babel/core@7.6.0
+ @babel/preset-env@7.6.0

三、新增 .babelrc 檔案

{
  "presets": ["@babel/preset-env"]
}

四、在 CLI 操作 gulp4。運行成功。(檔名改成 gulpfile.babel.js 後,CLI 會自動 requrie @babel/register)

gulp hello4ES6

[19:20:40] Requiring external module @babel/register
[19:20:42] Using gulpfile D:\Users\Chu\Desktop\test\Sweataste-gulp4.0\gulpfile.babel.js
[19:20:42] Starting 'hello4ES6'...
hello gulp 4.0, ES6 format
[19:20:42] Finished 'hello4ES6' after 275 ms

小結

最後的資料夾結構會長這樣

├─source
│   ├─images
│   ├─javascripts
│   └─stylesheets
│       ├─components
│       ├─helpers
│       └─pages
├─.babelrc
├─.gitignore
├─gulpfile.js
└─README.md 

關於 gulp 3.9.1、gulp4 CommonJS 與 gulp4 ESM 寫法的比較

// gulpfile.babel.js

import gulp from 'gulp' // ES6 引入模組寫法

// gulp 3.9.1 寫法
// var gulp = require('gulp') // CommonJS 引入模組寫法
gulp.task('hello3', function(cb){
  console.log('hello gulp 3.9.1')
  cb()
})

// gulp 4.0、CommonJS 寫法
// const gulp = require('gulp') // CommonJS 引入模組寫法
function hello4CommonJS(cb) {
  console.log('hello gulp 4.0, CommonJS format' )
  cb();
}
exports.hello4CommonJS = hello4CommonJS

// gulp 4.0、ES6 寫法
// import gulp from 'gulp' // ES6 引入模組寫法
export function hello4ES6(cb) {
  console.log('hello gulp 4.0, ES6 format')
  cb()
}

今天是 hello gulp 篇的第二篇,比較了 gulp 3.9.1 與 gulp 4 的 task 寫法差異。明天將會談 JavaScript 的 module 規範。

參考資料

官方

在 gulp 使用 import


上一篇
[試著把切版專案升級到 gulp4.0 吧] Day04 來自 gulp 的 hello world:gulp 3.9.1 寫法
下一篇
[試著把切版專案升級到 gulp4.0 吧] Day06 來自 gulp 的 hello world:JavaScript 模組化方案
系列文
試著把切版專案升級到 gulp4.0 吧36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Ray
iT邦研究生 4 級 ‧ 2019-09-22 16:02:13

說真的我個人還是比較習慣 gulp.task() 的寫法 XD

其實我也是 XD(畢竟我還沒把專案的 gulpfile 整個翻新過,對 gulp.task() 比較熟)

但感覺用 function 來替代 gulp.task() 會有幾個好處:

  1. 在 CLI 執行 gulp --tasks 看 task 清單時,沒有 export 出來的 task 就不會顯示出來,感覺會更簡潔。
  2. 如果學會用 function 制定 task,並用 export 導出 task 的話,對初學 gulp 的人就可以少學 gulp.task() 這支 API 了。

根據這兩個理由,雖然我目前也比較習慣 gulp.task() 的寫法,但接下來幾篇應該就會換成 gulp 4 推薦的 function + export 寫法 ~

對惹,我有拜讀過 Ray 寫的 gulp 系列文,覺得很受用。我的系列文要談的東西你幾乎都寫過了 XD

Ray iT邦研究生 4 級 ‧ 2019-09-22 17:11:03 檢舉

gulp --tasks (完全沒用過XD)

基本上我是覺得 function 寫法是比較接近原本 JavaScript 定義方式,所以對於初學是也不錯,另外 gulp4 我記得好像也推薦這種寫法

const fu = function () {...};
exports.build = series(fu);

當初我寫 Gulp 系列文章的時候,其實就是為了 Gulp 4 撰寫,但是我的詮釋方式大概就是會使用 gulp.task() <- 腦袋就是覺得這個比較直覺 ,純屬個人喜好XD

但是如果未來 gulp.task() 淘汰我是覺得也沒甚麼差就是了,只是換另一種寫法大同小異 XD

但是如果沒有淘汰這個 API 的話,我還是會寫 gulp.task() (任性)?!

後面就期待你會如何詮釋 Gulp XD

((突然發現我沒訂閱,怒訂閱一下

感謝 Ray 的 抖內 訂閱 ~

沒錯喔 ~ gulp4 也推薦 exports 的寫法,官方的推薦用法其實也是這個,這其實就是 Node.js 先前採用的 CommonJS 的模組規範。

不過現在 ES6 module 的寫法像是 exprotimport 已經開始慢慢在發展了,往後 Node.js 勢必會完全支援這個寫法,我就想說直接用 ES6 的寫法比較划算,讓我可以多學一點(欸?)

我要留言

立即登入留言